package com.mixsmart.commonweb.upload;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.mixsmart.commonweb.IWebConstant;
import com.mixsmart.commonweb.bean.entity.TCAttachment;
import com.mixsmart.commonweb.service.impl.AttachmentService;
import com.mixsmart.commonweb.upload.classify.UploadClassifyFactory;
import com.mixsmart.core.bean.MixResponse;
import com.mixsmart.core.config.SystemConfig;
import com.mixsmart.utils.StringUtils;

/**
 * 上传文件实现类
 * @author lmq
 * @version 1.0
 * @since JDK1.6以上
 * <br />
 * 2016年7月22日
 */
@Component
public class UploadFileImpl implements IUploadFile {
	
	private static final Logger logger = Logger.getLogger(UploadFileImpl.class);
	
	@Autowired
	private AttachmentService attServ;
	
	@Override
	public MixResponse<TCAttachment> upload(InputStream is, String fileName, 
			String contentType, long fileSize, String userId, Map<String, Object> params) {
		return this.uploadFileAndSave(is, fileName, contentType, fileSize, userId, null, params,
				this.getStorePath(fileName, null, contentType, params), null);
	}

	@Override
	public MixResponse<TCAttachment> upload(InputStream is, String fileName, String contentType, long fileSize,
			String userId, String attType, Map<String, Object> params) {
		return this.uploadFileAndSave(is, fileName, contentType, fileSize, userId, attType, params,
				this.getStorePath(fileName, null, contentType, params), null);
	}

	@Override
	public MixResponse<TCAttachment> upload(InputStream is, String fileName, String contentType, long fileSize,
			String userId, String attType, String targetDirPath, Map<String, Object> params) {
		return this.uploadFileAndSave(is, fileName, contentType, fileSize, userId, attType, params,
				targetDirPath, null);
	}

	@Override
	public MixResponse<TCAttachment> upload(InputStream is, String fileName, String contentType, long fileSize,
			String userId, String attType, String targetDirPath, String targetFileName) {
		return this.uploadFileAndSave(is, fileName, contentType, fileSize, userId, attType, null,
				targetDirPath, targetFileName);
	}

	@Override
	public String upload(InputStream is, String fileName, String contentType, boolean isUploadClassify, 
			String attType, String targetDirPath, String targetFileName) {
		if(isUploadClassify) {
			String realPath = this.getStorePath(fileName, attType, contentType, null);
			String uploadDir = UploadFileUtils.getUploadDir();
			if(targetDirPath.endsWith("/")) {
				targetDirPath = targetDirPath+realPath.replace(uploadDir+"/", "");
			} else {
				targetDirPath = targetDirPath+"/"+realPath.replace(uploadDir+"/", "");
			}
		}
		return this.uploadFile(is, fileName, targetDirPath, targetFileName);
	}

	@Override
	public String upload(InputStream is, String fileName, String contentType, boolean isUploadClassify, 
			String attType, String targetDirPath, Map<String, Object> params) {
		if(isUploadClassify) {
			String realPath = this.getStorePath(fileName, attType, contentType, params);
			String uploadDir = UploadFileUtils.getUploadDir();
			if(targetDirPath.endsWith("/")) {
				targetDirPath = targetDirPath+realPath.replace(uploadDir+"/", "");
			} else {
				targetDirPath = targetDirPath+"/"+realPath.replace(uploadDir+"/", "");
			}
		}
		return this.uploadFile(is, fileName, targetDirPath, null);
	}

	@Override
	public String upload(InputStream is, String fileName, String contentType,
			String attType, Map<String, Object> params) {
		return this.uploadFile(is, fileName, this.getStorePath(fileName, attType, contentType, params), null);
	}

	@Override
	public String upload(InputStream is, String fileName, String targetDirPath) {
		return this.uploadFile(is, fileName, targetDirPath, null);
	}
	
	/**
	 * 获取存储路径
	 * @param fileName
	 * @param attType
	 * @param contentType
	 * @param params
	 * @return 返回存储绝对路径目录
	 */
	private String getStorePath(String fileName, String attType, String contentType, Map<String,Object> params) {
		String classifyType = SystemConfig.getInstance().getValue("upload.classify");
		String realDirPath = null;
		logger.info("正在判断是否按类型归类附件...");
		String uploadDir = UploadFileUtils.getUploadDir();
		if(StringUtils.isNotEmpty(classifyType)) {
			logger.info("正在获取归类目录...");
			ClassifyModel classifyModel = new ClassifyModel(fileName, null, contentType);
			classifyModel.setParams(params);
			realDirPath = UploadClassifyFactory.getClassifyDir(classifyType, classifyModel);
			if(StringUtils.isNotEmpty(realDirPath) && !realDirPath.contains(uploadDir)) {
				realDirPath = uploadDir+"/"+realDirPath;
			}
			logger.info("归类类型为:["+classifyType+"],对应的目录为["+realDirPath+"]...");
		}
		if(StringUtils.isEmpty(realDirPath)) {
			realDirPath = uploadDir;
		}
		File path = new File(realDirPath);
		if(!path.exists()) {
			logger.info("该目录文件["+realDirPath+"]不存在，正在创建...");
			path.mkdirs();
			logger.info("目录文件["+realDirPath+"]创建[成功]...");
		}
		return realDirPath;
	}
	
	/**
	 * 上传文件并保存文件信息
	 * @param is
	 * @param fileName 原文件名
	 * @param contentType 文件类型
	 * @param fileSize 文件大小
	 * @param userId 上传用户
	 * @param attType 附件类型
	 * @param params 参数
	 * @return 返回MixResponse对象
	 */
	private MixResponse<TCAttachment> uploadFileAndSave(InputStream is, String fileName, String contentType, long fileSize,
			String userId, String attType, Map<String, Object> params, String targetDirPath, String targetFileName) {
		MixResponse<TCAttachment> mixResp = new MixResponse<TCAttachment>();
		if(this.isRequireParam(is, fileName, contentType, fileSize, userId)) {
			String fileSuffix = StringUtils.getFileSuffix(fileName);
			if(StringUtils.isEmpty(targetFileName)) {
				targetFileName = StringUtils.uuid()+"."+fileSuffix;
			}
			String realPath = targetDirPath + "/" + targetFileName;
			String uploadDirStr = UploadFileUtils.getUploadDir();
			String relativePath = realPath.replace(uploadDirStr+"/", "");
			logger.info("正在上传文件...");
			TCAttachment att = new TCAttachment(fileName, relativePath, contentType, fileSuffix, fileSize, userId, null);
			try {
				FileUtils.copyInputStreamToFile(is, new File(realPath));
				logger.info("文件上传[成功]...");
				logger.info("正在保存附件信息...");
				attServ.save(att);
				logger.info("附件信息保存[成功]...");
				mixResp.setResult(IWebConstant.OP_SUCCESS);
				mixResp.setMsg("上传文件成功");
				mixResp.setData(att);
			} catch (IOException e) {
				logger.error("上传文件[异常]...");
				e.printStackTrace();
			}
		}
		return mixResp;
	}
	
	/**
	 * 上传文件并保存文件信息
	 * @param is
	 * @param fileName 原文件名
	 * @param targetDirPath 文件类型
	 * @param targetFileName 文件大小
	 * @return 返回文件存放的路径
	 */
	private String uploadFile(InputStream is, String fileName ,String targetDirPath, String targetFileName) {
		String realPath = null;
		if(null != is && StringUtils.isNotEmpty(fileName)) {
			String fileSuffix = StringUtils.getFileSuffix(fileName);
			if(StringUtils.isEmpty(targetFileName)) {
				targetFileName = StringUtils.uuid()+"."+fileSuffix;
			}
			realPath = targetDirPath + "/" + targetFileName;
			try {
				FileUtils.copyInputStreamToFile(is, new File(realPath));
			} catch (IOException e) {
				e.printStackTrace();
				realPath = null;
			} catch (Exception e) {
				e.printStackTrace();
				realPath = null;
			}
		}
		return realPath;
	}
	
	/**
	 * 验证必须的参数
	 * @param is
	 * @param fileName
	 * @param contentType
	 * @param fileSize
	 * @param userId
	 * @return
	 */
	private boolean isRequireParam(InputStream is, String fileName, String contentType, 
			long fileSize, String userId) {
		return (null != is && StringUtils.isNotEmpty(fileName) 
				&& StringUtils.isNotEmpty(contentType) && StringUtils.isNotEmpty(userId) && 
				fileSize > 0);
	}
}
